package com.dhcc.DRGsHosp.facade.impl;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.inject.Named;

import org.dayatang.domain.InstanceFactory;
import org.dayatang.querychannel.QueryChannelService;
import org.dayatang.utils.Page;
import org.openkoala.koala.commons.InvokeResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import com.dhcc.DRGsHosp.application.CliSpecApplication;
import com.dhcc.DRGsHosp.core.domain.CliSpec;
import com.dhcc.DRGsHosp.facade.CliSpecFacade;
import com.dhcc.DRGsHosp.facade.dto.CliSpecDTO;
import com.dhcc.DRGsHosp.facade.impl.assembler.CliSpecAssembler;
import com.dhcc.DRGsHosp.infra.util.StringUtils;

/**
 * @title		: CliSpecFacadeImpl.java 
 * @description	: 
 * @author		: chl
 * @date		: 2016年12月7日
 * @version     : 2016
 * @copyright   : DHCC 
 */
@Named("drgsHospFacadeImpl2")
public class CliSpecFacadeImpl implements CliSpecFacade {
	@Autowired
	private CliSpecApplication cliSpecApplication ;
	
	@Autowired
	private NamedParameterJdbcTemplate jdbcTempSeverice; 
	
	private QueryChannelService queryChannel;
	
	private QueryChannelService getQueryChannelService(){
	   if(queryChannel==null){
	          queryChannel = InstanceFactory.getInstance(QueryChannelService.class,"queryChannel");
	   }
	 return queryChannel;
	}
	
	@Override
	public InvokeResult findAllCliSpecs() {
		List<CliSpecDTO> list = CliSpecAssembler.toDTOs(cliSpecApplication.findAllCliSpecs())  ;
		return InvokeResult.success(list);
	}

	@Override
	public Page<CliSpecDTO> pageJson(CliSpecDTO cliSpecDTO, int page,
			int pageSize) {
		StringBuilder jpql = new StringBuilder() ;
		jpql.append("select cs from CliSpec cs where 1=1 ") ;
		List<Object> conditions = new ArrayList<Object>() ;
		if( null != cliSpecDTO ){
			if(null != cliSpecDTO.getSpecDesc() && !"".equals(cliSpecDTO.getSpecDesc())){
				jpql.append("and cs.specDesc like ? ") ;
				conditions.add(MessageFormat.format("%{0}%", cliSpecDTO.getSpecDesc()));
			}
		}
		jpql.append("order by cs.specCode ") ;
		Page<CliSpec> pages = getQueryChannelService().createJpqlQuery(jpql.toString()).setParameters(conditions).setPage(page, pageSize).pagedList() ;
		return new Page<CliSpecDTO>(pages.getStart(), pages.getResultCount(),pageSize, CliSpecAssembler.toDTOs(pages.getData()));
	}

	@Override
	public Boolean isCodeExist(String specCode) {
		String jpql = "select count(cs.specCode) from CliSpec cs where cs.specCode = :specCode" ;
		Long count = (Long) getQueryChannelService().createJpqlQuery(jpql).addParameter("specCode", specCode).list().get(0) ;
		if(count > 0) {
			return true ;
		} else {
			return false ;
		}
	}

	@Override
	public InvokeResult save(CliSpecDTO cliSpecDTO) {
		if(null != cliSpecDTO) {
 		cliSpecApplication.save(CliSpecAssembler.toEntity(cliSpecDTO));
		}
		return InvokeResult.success();
	}

	@Override
	public InvokeResult delete(String specCodes) {
		String[] value = specCodes.split("】【");
        String[] codeArrs = new String[value.length];
        StringBuffer depDesc = new StringBuffer() ;
        for (int i = 0; i < value.length; i ++) {
        	codeArrs[i] = value[i];
        	Map<String, Object> condition = new HashMap<>();
        	condition.put("specCode", codeArrs[i]) ;
        	// 判断改临床专业有没有被科室选择
        	String sql_1  = " select (select count(1) from drgs.t_departmentdrg  dd \n" +
        				" where dd.parspec_code = :specCode) count,clispec.spec_desc \n" + 
        					" from drgs.t_clispec clispec \n" +
        						" where clispec.spec_code = :specCode \n";
        	List<Object> result = cliSpecApplication.excuteQuery(sql_1, condition) ;
        	Integer count =  Integer.valueOf(((Object[])(result.get(0)))[0].toString())  ;
        	if( count > 0 ){
        		depDesc.append(((Object[])(result.get(0)))[1].toString() + " ") ;
        		continue ;
        	}
        	cliSpecApplication.deleteByCode(codeArrs[i]);
        	// 删除临床专业与ADRG的关系
        	String sql = "delete from drgs.t_clispecdrgs cd where cd.csd_spec_code = :specCode " ;
			cliSpecApplication.excuteUpdate(sql, condition ) ;
		}
		return InvokeResult.success(depDesc);
	}

	@Override
	public InvokeResult update(CliSpecDTO cliSpecDTO) {
		if( null != cliSpecDTO.getSpecCode() && !"".equals(cliSpecDTO.getSpecCode())){
			// 先查询有没有
			Map<String,Object> map = new HashMap<String,Object>() ;
			String specDesc = cliSpecDTO.getSpecDesc()!=null ? cliSpecDTO.getSpecDesc(): "" ;
			String specMark = cliSpecDTO.getSpecMark()!=null ? cliSpecDTO.getSpecMark(): "" ;
			map.put("specDesc", specDesc) ;
			map.put("specMark", specMark) ;
			map.put("specCode",  cliSpecDTO.getSpecCode()) ;
			cliSpecApplication.update(map);
		} 
		return InvokeResult.success();
	}
	/**
	 * 
	 *  @Description：
	 *  @Author ChenHanlin  
	 *  @see com.dhcc.DRGsHosp.facade.CliSpecFacade#getDrgTree(java.lang.String, java.lang.String)
	 */
	@Override
	public InvokeResult getDrgTree(String specCode,String version) {
		List<Map<String,Object>> nodeList = new ArrayList<Map<String,Object>>() ;
		// 保存已经选中的节点code
		Set<String> nodeSet = new HashSet<>() ;
		// 用于去除重复节点
		Set<Map<String,Object>> setMap = new HashSet<Map<String,Object>>();  
		// 查询ADRG和DRG，并构造ztree节点
		StringBuffer strb = new StringBuffer() ;
		strb.append(" select  mdc.mdc_code,mdc.mdc_desc, adrg.adrg_code,adrg.adrg_desc,drg.drg_code, \n ") ;
		strb.append(" drg.drg_desc, decode( csd_drg_code,null,'false','true') checked , decode( dd.pardrg_code,null,'false','true') disabled  \n ") ;
		strb.append(" from drgs.t_drgs drg  \n ") ; 
		strb.append(" left join drgs.t_adrg adrg \n ") ;
		strb.append(" on adrg.adrg_code = drg.adrg_code and adrg.ver_code = drg.ver_code \n ") ;
		strb.append(" left join drgs.t_mdcgroup mdc  \n ") ;
		strb.append(" on adrg.mdc_code = mdc.mdc_code and mdc.ver_code = adrg.ver_code  \n ") ;
		strb.append(" left join drgs.t_clispecdrgs cd   \n ") ;
		strb.append(" on drg.drg_code= cd.csd_drg_code and drg.ver_code = cd.csd_ver_code and cd.csd_spec_code = :specCode \n ") ;
		strb.append(" left join drgs.t_departmentdrg dd on dd.pardrg_code = cd.csd_drg_code and dd.version = cd.csd_ver_code and dd.parspec_code = cd.csd_spec_code \n ") ;
		strb.append(" where drg.ver_code = :version \n ") ;
		strb.append(" order by  mdc.mdc_code,adrg.adrg_code,drg.drg_code \n ") ;
		Map<String,Object> paramMap = new HashMap<>();
		paramMap.put("specCode", specCode ) ;
		paramMap.put("version", version ) ;
		List<Map<String,Object>> mapList = jdbcTempSeverice.queryForList(strb.toString(), paramMap) ;
		// 设置节点属性
		for(Map<String,Object> node : mapList) {
			Map<String,Object> nodeMdc = new HashMap<String,Object>() ;
			Map<String,Object> nodeAdrg = new HashMap<String,Object>() ;
			Map<String,Object> nodeDrg = new HashMap<String,Object>() ;
			// 设置节点的 ID PID
			nodeMdc.put("id", node.get("MDC_CODE")) ;
			nodeMdc.put("pid",0) ;
			nodeAdrg.put("id", node.get("ADRG_CODE")) ;
			nodeAdrg.put("pid", node.get("MDC_CODE")) ;
			nodeDrg.put("id", node.get("DRG_CODE")) ;
			nodeDrg.put("pid", node.get("ADRG_CODE")) ;
			// 设置节点名称
			if(node.get("MDC_DESC") != null){
				nodeMdc.put("name",node.get("MDC_CODE") +"-"+ node.get("MDC_DESC")) ;
			} else {
				nodeMdc.put("name",node.get("MDC_CODE")) ;
			}
			if(node.get("ADRG_DESC") != null){
				nodeAdrg.put("name",node.get("ADRG_CODE") +"-"+ node.get("ADRG_DESC")) ;
			} else {
				nodeAdrg.put("name",node.get("ADRG_CODE")) ;
			}
			if(node.get("DRG_DESC") != null){
				nodeDrg.put("name",node.get("DRG_CODE") +"-"+ node.get("DRG_DESC")) ;
			} else {
				nodeDrg.put("name",node.get("DRG_CODE")) ;
			}
			// 设置选中及展开状态
			boolean checkded = Boolean.valueOf(node.get("CHECKED").toString()) ;
			// 已经设置为true 的父节点不再设置为false
			if(checkded) {
				nodeSet.add(node.get("ADRG_CODE").toString()) ;
				nodeSet.add(node.get("MDC_CODE").toString()) ;
				nodeDrg.put("checked", true) ;
			}  
			// 设置失效状态，（已经被科室选中的设置为失效）
			boolean disabled = Boolean.valueOf(node.get("DISABLED").toString()) ;
			if(disabled) {
 				nodeDrg.put("chkDisabled", true) ;
			}
			if(setMap.add(nodeMdc)) {
				nodeList.add(nodeMdc) ;
			}
			if(setMap.add(nodeAdrg)) {
				nodeList.add(nodeAdrg) ;
			}
			if(setMap.add(nodeDrg)) {
				nodeList.add(nodeDrg) ;
			}
		}
		for (Map<String,Object> mapNode : nodeList) {
			// 不是MDC节点
			if(nodeSet.contains(mapNode.get("id")) && !(0 + "").equals(mapNode.get("pid").toString())) {
				mapNode.put("open", true) ;
				mapNode.put("checked", true) ;
			} else if(nodeSet.contains(mapNode.get("id")) && (0 + "").equals(mapNode.get("pid").toString())) {// mdc节点
				mapNode.put("checked", true) ;
				mapNode.put("open", true) ;
			}
		}
		return InvokeResult.success(nodeList);
	}
	/**
	 * 
	 *  @Description：
	 *  @Author ChenHanlin  
	 *  @see com.dhcc.DRGsHosp.facade.CliSpecFacade#saveDrgsNode(java.lang.String, java.lang.String, java.lang.String[])
	 */
	@Override
	public InvokeResult saveDrgsNode(String specCode, String version,
			String[] drgsNodes) {
		String sql = null ;
		Map<String, Object> condition = new HashMap<>();
		Map<String, Object> condition_0 = new HashMap<>();
		specCode = specCode != null ? specCode : "" ;
		version = version != null ? version : "" ;
		condition.put("specCode", specCode) ;
		condition.put("version", version) ;
		condition_0.putAll(condition);
		if(drgsNodes == null){ // 删除 临床专业下所有ADRG
			sql = "delete from drgs.t_clispecdrgs  cd where cd.csd_spec_code = :specCode and cd.csd_ver_code = :version" ;
			cliSpecApplication.excuteUpdate(sql, condition);
		} else {
			String drgsNodesStr = StringUtils.convertArrayToQuoteString(drgsNodes) ;
			sql = "select 1 from drgs.t_clispecdrgs  cd where cd.csd_spec_code = :specCode and cd.csd_ver_code = :version and cd.csd_drg_code not in (" + drgsNodesStr +")" ;
			List<Object> countList = cliSpecApplication.excuteQuery(sql, condition) ;
			if(countList.size() > 0){ // 用户有取消的选项
				// 删除取消的选项																								//  (" +param+")" 
				sql = "delete from drgs.t_clispecdrgs cd where cd.csd_spec_code = :specCode and cd.csd_ver_code = :version and cd.csd_drg_code not in (" + drgsNodesStr +")"  ;
				cliSpecApplication.excuteUpdate(sql, condition);
			}  
				// 对 选项 保存或更新
			for(String drgCode:drgsNodes) {
				drgCode = (drgCode!=null?drgCode:"");
				condition_0.put("drgCode", drgCode) ;
				sql = "select cd.csd_id from drgs.t_clispecdrgs cd where cd.csd_spec_code = :specCode and cd.csd_drg_code = :drgCode and cd.csd_ver_code = :version " ;
				List<Object> list = cliSpecApplication.excuteQuery(sql, condition_0 ) ;
				if(list!= null && list.size() == 0 ) {
					// 增加
					sql = "insert into drgs.t_clispecdrgs cd (cd.csd_id,cd.csd_spec_code , cd.csd_drg_code , cd.csd_ver_code) values ('"+(UUID.randomUUID().toString().replaceAll("-", ""))+"',:specCode , :drgCode , :version )" ;
					cliSpecApplication.excuteUpdate(sql, condition_0) ;
				}
			}
		}
		return InvokeResult.success();
	}

	/**
	 * 
	 *  @Description：
	 *  @Author ChenHanlin  
	 *  @see com.dhcc.DRGsHosp.facade.CliSpecFacade#findDrgsBySpec(java.lang.String)
	 */
	@Override
	public InvokeResult findDrgsBySpec(String specCode) {
		List<Object> resultList = new ArrayList<>() ;
		List<Object> listVersion = new ArrayList<Object>() ;
		Map<String, Object> condition = new HashMap<>();
		String specCode_0 = specCode != null ? specCode : "" ;
		condition.put("specCode", specCode_0 ) ;
		// 先查询某个临床专业下选了几个版本
		String sqlVersion = " select distinct cd.csd_ver_code,dv.ver_desc from drgs.t_clispecdrgs cd \n"
				+ " left join drgs.T_DRGVERSION dv on cd.csd_ver_code = dv.ver_code \n" 
				+ " where  cd.csd_spec_code =  :specCode \n" ;
		listVersion = cliSpecApplication.excuteQuery(sqlVersion, condition) ; 
		if(listVersion != null && listVersion.size() >0 ){
			for(Object obj : listVersion){
				Map<String,Object> resultMap = new HashMap<>() ;
				/**
				 * Adrg 列表
				 */
				String version = (String) (((Object[])obj)[0] !=null ? ((Object[])obj)[0] : "") ;
				String verDesc = (String) (((Object[])obj)[1] !=null ? ((Object[])obj)[1] : "") ;
				// 查询 临床专业下 某版本的 DRG
				StringBuffer strb = new StringBuffer() ;
				strb.append(" select drg.drg_code,drg.drg_desc,adrg.adrg_code,adrg.adrg_desc,adrg.mdc_code,adrg.ver_code from drgs.t_clispecdrgs cd  \n ") ;
				strb.append(" left join drgs.t_drgs drg on drg.drg_code = cd.csd_drg_code and drg.ver_code = cd.csd_ver_code \n ") ;
				strb.append(" left join drgs.t_adrg adrg on adrg.adrg_code = drg.adrg_code and adrg.ver_code = drg.ver_code \n ") ;
				strb.append(" where cd.csd_spec_code = :specCode and drg.drg_code is not null and cd.csd_ver_code = :verCode \n ") ;
				condition.put("verCode", version) ;
				List<Map<String,Object>> drgsList = jdbcTempSeverice.queryForList(strb.toString(), condition) ;
				resultMap.put("version", version) ;
				resultMap.put("verDesc", verDesc) ;
				resultMap.put("drgsList", drgsList) ;
				resultList.add(resultMap) ;
			}
		}
		return InvokeResult.success(resultList) ;
	}
	/**
	 * 
	 *  @Description：
	 *  @Author ChenHanlin  
	 *  @see com.dhcc.DRGsHosp.facade.CliSpecFacade#getSpecTree(java.lang.String, java.lang.String)
	 */
	@Override
	public InvokeResult getSpecTree(String depCode,String verCode) {
 		List<Map<String,Object>> nodeList = new ArrayList<Map<String,Object>>() ;
		Map<String,Object> resultMap = new HashMap<>() ;
		// 保存已经选中的节点code
		Set<String> nodeSet = new HashSet<>() ;
		// 用于去除重复数据
		Set<Map<String,Object>> setMap = new HashSet<Map<String,Object>>();  
		StringBuffer sql = new StringBuffer();
		Map<String, Object> condition = new HashMap<>() ;
		sql.append(" select cd.csd_spec_code,cs.spec_desc, mdc.mdc_code mdc_code,mdc.mdc_desc, adrg.adrg_code adrg_code,adrg.adrg_desc, \n ") ;
		sql.append(" drg.drg_code drg_code,drg.drg_desc ,decode(dd.pardrg_code,null,'false','true') checked  \n ") ;
		sql.append(" from drgs.t_clispecdrgs cd  \n ") ;
		sql.append(" left join drgs.t_departmentdrg dd on dd.parspec_code = cd.csd_spec_code and dd.pardrg_code = cd.csd_drg_code and cd.csd_ver_code = dd.version and dd.pardep_code = :depCode \n ") ;
		sql.append(" left join drgs.t_drgs drg on cd.csd_drg_code = drg.drg_code and cd.csd_ver_code  = drg.ver_code \n ") ;
		sql.append(" left join drgs.t_adrg adrg on adrg.adrg_code = drg.adrg_code and adrg.ver_code = drg.ver_code \n ") ;
		sql.append(" left join drgs.t_mdcgroup mdc on mdc.mdc_code = adrg.mdc_code and mdc.ver_code = drg.ver_code \n ") ;
		sql.append(" left join drgs.t_clispec cs on  cs.spec_code = cd.csd_spec_code \n ") ;
		sql.append(" where cd.csd_ver_code = :verCode and drg.ver_code is not null order by to_number(cd.csd_spec_code) \n ") ;
		sql.append(" \n ") ;
		condition.put("verCode", verCode) ;
		condition.put("depCode", depCode) ;
		List<Map<String,Object>> mapList = jdbcTempSeverice.queryForList(sql.toString(),condition) ;
		// 判断是否有与临床专业对应的adrg 
		if(null != mapList && mapList.size() > 0) { //有临床专业与ADRG的对照关系
			resultMap.put("msg", true) ; //有临床专业与ADRG的对照关系
			for(Map<String,Object> node :  mapList) {
				Map<String,Object> nodeSpec = new HashMap<String,Object>() ;
				Map<String,Object> nodeMdc = new HashMap<String,Object>() ;
				Map<String,Object> nodeAdrg = new HashMap<String,Object>() ;
				Map<String,Object> nodeDrg = new HashMap<String,Object>() ;
				nodeSpec.put("id", node.get("CSD_SPEC_CODE")) ;
				nodeSpec.put("pid",0) ;
//				nodeSpec.put("nocheck", true) ;
				nodeMdc.put("id", node.get("CSD_SPEC_CODE")+"#"+node.get("MDC_CODE")) ;
				nodeMdc.put("pid",node.get("CSD_SPEC_CODE")) ;
				nodeAdrg.put("id", node.get("CSD_SPEC_CODE")+"#"+node.get("ADRG_CODE")) ;
				nodeAdrg.put("pid",node.get("CSD_SPEC_CODE")+"#"+node.get("MDC_CODE")) ;
				nodeDrg.put("id", node.get("CSD_SPEC_CODE")+"#"+node.get("DRG_CODE")) ;
				nodeDrg.put("pid",node.get("CSD_SPEC_CODE")+"#"+node.get("ADRG_CODE")) ;
				// 设置节点名称 
				if(node.get("SPEC_DESC") != null) {
					nodeSpec.put("name",node.get("CSD_SPEC_CODE") +"-"+ node.get("SPEC_DESC")) ;
				} else {
					nodeSpec.put("name",node.get("CSD_SPEC_CODE")) ;
				}
				if(node.get("MDC_DESC") != null) {
					nodeMdc.put("name",node.get("MDC_CODE") +"-"+ node.get("MDC_DESC")) ;
				} else {
					nodeMdc.put("name",node.get("MDC_CODE")) ;
				}
				if(node.get("ADRG_DESC") != null) {
					nodeAdrg.put("name",node.get("ADRG_CODE") +"-"+ node.get("ADRG_DESC")) ;
				} else {
					nodeAdrg.put("name",node.get("ADRG_CODE")) ;
				}
				if(node.get("DRG_DESC") != null) {
					nodeDrg.put("name",node.get("DRG_CODE") +"-"+ node.get("DRG_DESC")) ;
				} else {
					nodeDrg.put("name",node.get("DRG_CODE")) ;
				}
				// 设置选中及展开状态
				boolean flag = Boolean.valueOf(node.get("CHECKED").toString()) ;
				// 已经设置为true 的父节点都 不再设置为false
				if(flag) {
					nodeSet.add(node.get("CSD_SPEC_CODE").toString()) ;
					nodeSet.add(node.get("CSD_SPEC_CODE")+"#"+node.get("MDC_CODE").toString()) ;
					nodeSet.add(node.get("CSD_SPEC_CODE")+"#"+node.get("ADRG_CODE").toString()) ;
					nodeDrg.put("checked", true) ;
				}
				if(setMap.add(nodeSpec)) {
					nodeList.add(nodeSpec) ;
				}
				if(setMap.add(nodeMdc)) {
					nodeList.add(nodeMdc) ;
				}
				if(setMap.add(nodeAdrg)) {
					nodeList.add(nodeAdrg) ;
				}
				if(setMap.add(nodeDrg)) {
					nodeList.add(nodeDrg) ;
				}
			}
		} else {
			resultMap.put("msg", false ) ; 
		}
		for (Map<String,Object> mapNode : nodeList) {
			// 临床专业节点
//			if(nodeSet.contains(mapNode.get("id")) && !(0 + "").equals(mapNode.get("pid").toString())) {
//				mapNode.put("open", true) ;
//				mapNode.put("checked", true) ;
//			} else 
			if(nodeSet.contains(mapNode.get("id"))) {
					mapNode.put("open", true) ;
					mapNode.put("checked", true) ;
			}
		}
		resultMap.put("nodeList", nodeList) ;
		return InvokeResult.success( resultMap );
	}
}
